<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>Java games animation</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Java, Swing, tutorial, Animation, programming, GUI, multiplatform">
<meta name="description" content="This part of the Java games tutorial covers animation.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>


<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Animation</h1>


<p>
In this part of the Java 2D games tutorial, we will work with animation. 
</p>

<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* LargeSquare */
google_ad_slot = "5070696322";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>

<p>
<b>Animation</b> is a rapid display of sequence of images which creates 
an illusion of movement. We will animate a star on our Board. We will 
implement the movement in three basic ways. We will use a Swing timer, 
a standard utility timer and a thread. 
</p>


<h2>Swing timer</h2>

<p>
In the first example we will use a Swing timer to create animation. 
This is the easiest but also the least effective way of animating objects 
in Java games. 
</p>

<div class="codehead">Star.java</div>
<pre class="code">
package star;

import javax.swing.JFrame;

public class Star extends JFrame {

    public Star() {

        add(new Board());

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(280, 240);
        setLocationRelativeTo(null);
        setTitle("Star");
        setResizable(false);
        setVisible(true);

    }

    public static void main(String[] args) {
        new Star();
    }
}
</pre>

<p>
This is the main class for the code example. 
</p>

<div class="codehead">Board.java</div>
<pre class="code">
package star;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Board extends JPanel implements ActionListener {

    Image star;
    Timer timer;
    int x, y;

    public Board() {
        setBackground(Color.BLACK);

        ImageIcon ii =
            new ImageIcon(this.getClass().getResource("star.png"));
        star = ii.getImage();

        setDoubleBuffered(true);

        x = y = 10;
        timer = new Timer(25, this);
        timer.start();
    }


    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D g2d = (Graphics2D)g;
        g2d.drawImage(star, x, y, this);
        Toolkit.getDefaultToolkit().sync();
        g.dispose();
    }


    public void actionPerformed(ActionEvent e) {
 
        x += 1;
        y += 1;

        if (y > 240) {
            y = -45;
            x = -45;
        }
        repaint();  
    }
}
</pre>

<pre class="explanation">
 setDoubleBuffered(true);
</pre>

<p>
Our JPanel component will use a buffer to paint. This means that all 
drawing will be done in memory first. Later the off-screen buffer will be 
copied to the screen. In this example, I didn't notice any differences. 
</p>

<pre class="explanation">
timer = new Timer(25, this);
timer.start();
</pre>

<p>
Here we create a Swing <code>Timer</code> class. We start the timer. 
Every 25 ms the timer will call the <code>actionPerformed()</code> method. 
In order to use the <code>actionPerformed()</code> method, we must implement 
the <code>ActionListener</code> interface. 
</p>

<pre class="explanation">
g2d.drawImage(star, x, y, this);
</pre>

<p>
In the <code>paint()</code> method, we draw the star. 
</p>

<pre class="explanation">
Toolkit.getDefaultToolkit().sync();
</pre>

<p>
We must synchronize the painting on Linux systems. Otherwise, the animation would not be smooth. 
</p>

<pre class="explanation">
public void actionPerformed(ActionEvent e) {
    x += 1;
    y += 1;

    if (y > 240) {
        y = -45;
        x = -45;
    }
    repaint();  
}
</pre>

<p>
In the <code>actionPerformed()</code> method we increase the x, y values. 
Then we call the <code>repaint()</code> method. This way
we regularly repaint the <code>Board</code> thus making the animation.
</p>


<img src="/img/gfx/javagames/star.png" alt="Star">
<div class="figure">Figure: Star</div>


<h2>Utility timer</h2>


<p>
This is very similar to the previous way. We use the java.util.Timer instead of the javax.Swing.Timer. 
For Java Swing games this way should be more accurate. 
</p>

<div class="codehead">Star.java</div>
<pre class="code">
package star2;

import javax.swing.JFrame;

public class Star extends JFrame {

    public Star() {

        add(new Board());

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(280, 240);
        setLocationRelativeTo(null);
        setTitle("Star");
        setResizable(false);
        setVisible(true);

    }

    public static void main(String[] args) {
        new Star();
    }
}
</pre>

<p>
The main class. 
</p>


<div class="codehead">Board.java</div>
<pre class="code">
package star2;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;

import java.util.Timer;
import java.util.TimerTask;

import javax.swing.ImageIcon;
import javax.swing.JPanel;


public class Board extends JPanel  {

    Image star;
    Timer timer;
    int x, y;

    public Board() {
        setBackground(Color.BLACK);

        ImageIcon ii = new ImageIcon(this.getClass().getResource("star.png"));
        star = ii.getImage();

        setDoubleBuffered(true);

        x = y = 10;
        timer = new Timer();
        timer.scheduleAtFixedRate(new ScheduleTask(), 100, 10);
    }


    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D g2d = (Graphics2D)g;
        g2d.drawImage(star, x, y, this);
        Toolkit.getDefaultToolkit().sync();
        g.dispose();
    }


    class ScheduleTask extends TimerTask {

        public void run() {
            x += 1;
            y += 1;

            if (y > 240) {
                y = -45;
                x = -45;
            }
            repaint();
        }
    }
}
</pre>

<p>
In this example, the timer will regularly call the <code>run()</code> 
method of the <code>ScheduleTask</code> class. 
</p>


<pre class="explanation">
timer = new Timer();
timer.scheduleAtFixedRate(new ScheduleTask(), 100, 10);
</pre>

<p>
Here we create a timer. And schedule a task at 10 ms interval. There is 100 ms initial delay. 
</p>


<pre class="explanation">
public void run() {
...
}
</pre>

<p>
Each 10 ms the timer will call this <code>run()</code> method. 
</p>


<h2>Thread</h2>

<p>
Animating objects using a thread is the most effective way of animation. 
</p>

<div class="codehead">Star.java</div>
<pre class="code">
package star3;

import javax.swing.JFrame;

public class Star extends JFrame {

    public Star() {

        add(new Board());

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(280, 240);
        setLocationRelativeTo(null);
        setTitle("Star");
        setResizable(false);
        setVisible(true);
    }

    public static void main(String[] args) {
        new Star();
    }
}
</pre>

<p>
This is the main class. 
</p>

<div class="codehead">Board.java</div>
<pre class="code">
package star2;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;

import javax.swing.ImageIcon;
import javax.swing.JPanel;


public class Board extends JPanel implements Runnable {

    private Image star;
    private Thread animator;
    private int x, y;

    private final int DELAY = 50;


    public Board() {
        setBackground(Color.BLACK);
        setDoubleBuffered(true);

        ImageIcon ii = new ImageIcon(this.getClass().getResource("star.png"));
        star = ii.getImage();

        x = y = 10;
    }

    public void addNotify() {
        super.addNotify();
        animator = new Thread(this);
        animator.start();
    }

    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D g2d = (Graphics2D)g;
        g2d.drawImage(star, x, y, this);
        Toolkit.getDefaultToolkit().sync();
        g.dispose();
    }


    public void cycle() {

        x += 1;
        y += 1;

        if (y > 240) {
            y = -45;
            x = -45;
        }
    }

    public void run() {

        long beforeTime, timeDiff, sleep;

        beforeTime = System.currentTimeMillis();

        while (true) {

            cycle();
            repaint();

            timeDiff = System.currentTimeMillis() - beforeTime;
            sleep = DELAY - timeDiff;

            if (sleep &lt; 0)
                sleep = 2;
            try {
                Thread.sleep(sleep);
            } catch (InterruptedException e) {
                System.out.println("interrupted");
            }

            beforeTime = System.currentTimeMillis();
        }
    }
}
</pre>

<p>
In the previous examples, we executed a task at specific intervals. 
In this example, the animation will take place inside a thread. 
The <code>run()</code> method is called only once. That's 
why we have a while loop in the method. From this method, we call 
the <code>cycle()</code> and the <code>repaint()</code> methods. 
</p>


<pre class="explanation">
public void addNotify() {
    super.addNotify();
    animator = new Thread(this);
    animator.start();
}
</pre>

<p>
The <code>addNotify()</code> method is called after our 
<code>JPanel</code> has been added to the <code>JFrame</code> 
component. This method is often used for various initialization tasks.
</p>

<p>
We want our game run smoothly. At constant speed. Therefore we compute the system time. 
</p>

<pre class="explanation">
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = DELAY - timeDiff;
</pre>

<p>
The <code>cycle()</code> and the <code>repaint()</code> 
methods might take different time at various while cycles. We calculate the 
time both methods run and subtract it from the DELAY constant. 
This way we want to ensure that each while cycle runs a constant time. In our case, 50ms each cycle. 
</p>


<p>
This part of the Java 2D games tutorial covered animation.
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>

<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified September 27, 2008  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
